﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.SqlClient;
using System.Data;

namespace GestorDeFlotas.Core
{
    public class Viaje
    {
        public Chofer Chofer { get; set; }
        public Turno Turno { get; set; }
        public int Fichas { get; set; }
        public DateTime FechaHora { get; set; }
        public Cliente Cliente { get; set; }

        public void Registrar()
        {
            this.ValidarParametros();

            using (SqlConnection connection = SqlUtils.GetConnection())
            {
                connection.Open();
                string sql = "INSERT INTO [CRAZY_TAXI].[TL_VIAJES] ([via_cant_fichas],[via_fecha],[viacho_id],[viacli_codigo],[viatur_id]) VALUES " +
                            "(@Fichas, @Fecha, @Chofer, @Cliente, @Turno)";
                SqlCommand registrarViaje = SqlUtils.GetNewCommand(sql);

                SqlParameter paramFichas = new SqlParameter("@Fichas", SqlDbType.Int);
                paramFichas.IsNullable = false;
                paramFichas.Value = this.Fichas;

                SqlParameter paramFecha = new SqlParameter("@Fecha", SqlDbType.DateTime);
                paramFecha.IsNullable = false;
                paramFecha.Value = this.FechaHora;

                SqlParameter paramChofer = new SqlParameter("@Chofer", SqlDbType.Int);
                paramChofer.IsNullable = false;
                paramChofer.Value = this.Chofer.Id;

                SqlParameter paramCliente = new SqlParameter("@Cliente", SqlDbType.Int);
                paramCliente.IsNullable = true;
                paramCliente.Value = this.Cliente == null ? DBNull.Value : (object)this.Cliente.Id;

                SqlParameter paramTurno = new SqlParameter("@Turno", SqlDbType.Int);
                paramTurno.IsNullable = false;
                paramTurno.Value = this.Turno.Id;

                registrarViaje.Parameters.Add(paramFichas);
                registrarViaje.Parameters.Add(paramFecha);
                registrarViaje.Parameters.Add(paramChofer);
                registrarViaje.Parameters.Add(paramCliente);
                registrarViaje.Parameters.Add(paramTurno);
                registrarViaje.Connection = connection;
                registrarViaje.ExecuteNonQuery();
            }
        }

        private void ValidarParametros()
        {
            if (!(this.Cliente == null) && !this.Cliente.Activo)
            {
                throw new Exception(string.Format("El cliente {0} no está Activo.", this.Cliente.Id));
            }

            if (!this.Chofer.Activo)
            {
                throw new Exception(string.Format("El chofer {0} no está Activo.", this.Chofer.Id));
            }

            if (!this.Turno.Activo)
            {
                throw new Exception(string.Format("El turno {0} no está Activo.", this.Turno.Id));
            }

            ValidarAuto();                        
            if (!(this.Cliente == null)) ValidarViajeRepetido();
        }

        private void ValidarAuto()
        {
            string sql = "SELECT [auto_codigo] " +
                ",[auto_reloj_codigo]" +
                ",[auto_es_activo]" +
                ",[reloj_es_activo]" +
                " FROM [CRAZY_TAXI].[TL_ChoferesPorAutoYTurno] " +
                " INNER JOIN [CRAZY_TAXI].[TL_Autos] ON catauto_codigo = auto_codigo" +
                " INNER JOIN [CRAZY_TAXI].[TL_Relojes] ON auto_reloj_codigo = reloj_codigo" +
                " WHERE catcho_id = @ChoferId AND cattur_id = @TurnoId AND cat_fecha >= @FechaInicio AND cat_fecha < @FechaFin";

            SqlCommand validarAuto = SqlUtils.GetNewCommand(sql);
            int codAuto;
            int codReloj;
            bool autoActivo;
            bool relojActivo;

            SqlParameter paramChofer = new SqlParameter("@ChoferId", SqlDbType.Int);
            paramChofer.IsNullable = false;
            paramChofer.Value = this.Chofer.Id;

            SqlParameter paramTurno = new SqlParameter("@TurnoId", SqlDbType.Int);
            paramTurno.IsNullable = false;
            paramTurno.Value = this.Turno.Id;

            SqlParameter paramFechaInicio = new SqlParameter("@FechaInicio", SqlDbType.DateTime);
            paramFechaInicio.IsNullable = false;
            paramFechaInicio.Value = this.FechaHora.Date;

            SqlParameter paramFechaFin = new SqlParameter("@FechaFin", SqlDbType.DateTime);
            paramFechaFin.IsNullable = false;
            paramFechaFin.Value = this.FechaHora.Date.AddDays(1);

            validarAuto.Parameters.Add(paramChofer);
            validarAuto.Parameters.Add(paramTurno);
            validarAuto.Parameters.Add(paramFechaInicio);
            validarAuto.Parameters.Add(paramFechaFin);

            using (SqlConnection connection = SqlUtils.GetConnection())
            {
                connection.Open();
                validarAuto.Connection = connection;
                using (SqlDataReader reader = validarAuto.ExecuteReader())
                {
                    if (reader.HasRows)
                    {
                        reader.Read();
                        codAuto = reader.GetInt32(0);
                        codReloj = reader.GetInt32(1);
                        autoActivo = reader.GetBoolean(2);
                        relojActivo = reader.GetBoolean(3);
                    }
                    else
                    {
                        throw new Exception(string.Format("El chofer {0} no tiene auto asignado en el turno {1} en la fecha {2}.", this.Chofer.Id, this.Turno.Id, this.FechaHora.Date.ToShortDateString()));
                    }
                }
            }
            
            if (!autoActivo)
            {
                throw new Exception(string.Format("El auto {0} asignado al chofer {1} en la fecha {2} no está Activo.",
                    codAuto,
                    this.Chofer.Id,
                    this.FechaHora.Date.ToShortDateString()));
            }

            if (!relojActivo)
            {
                throw new Exception(string.Format("El auto {0} asignado al chofer {1} en la fecha {2} posee el reloj {3} que no está Activo.",
                    codAuto,
                    this.Chofer.Id,
                    this.FechaHora.Date.ToShortDateString(),
                    codReloj));
            }
        }

        private void ValidarViajeRepetido()
        {
            string sql = "SELECT COUNT([via_id])" +
                " FROM [CRAZY_TAXI].[TL_VIAJES]" +
                " WHERE viacli_codigo = @ClienteId and via_fecha = @Fecha";

            SqlCommand validarViajesRepetidos = SqlUtils.GetNewCommand(sql);
            int viajesRepetidos;

            SqlParameter paramCliente = new SqlParameter("@ClienteId", SqlDbType.Int);
            paramCliente.IsNullable = false;
            paramCliente.Value = this.Cliente.Id;

            SqlParameter paramFecha = new SqlParameter("@Fecha", SqlDbType.DateTime);
            paramFecha.IsNullable = false;
            paramFecha.Value = this.FechaHora;

            validarViajesRepetidos.Parameters.Add(paramCliente);
            validarViajesRepetidos.Parameters.Add(paramFecha);

            using (SqlConnection connection = SqlUtils.GetConnection())
            {
                connection.Open();
                validarViajesRepetidos.Connection = connection;
                viajesRepetidos = Convert.ToInt32(validarViajesRepetidos.ExecuteScalar());
            }

            if (viajesRepetidos > 0)
            {
                throw new Exception(string.Format("El cliente {0} ya ha realizado un viaje en la fecha {1}.",                     
                    this.Cliente.Id,
                    this.FechaHora.ToString()));
            }
        }
    }
}
